package edu.server.dominio;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Session;

import edu.server.repositorio.OrdenFabricacionGeneral;
import edu.server.repositorio.RenglonOrdenFabricacionGeneral;
import edu.server.repositorio.RenglonOrdenPedido;
import edu.server.util.HibernateUtil;

public class D_OrdenFabricacionGeneral {

	public D_OrdenFabricacionGeneral()
	{
		
	}
	
	/**
	 * Método que registra una orden de fabricación en la base de datos.
	 * @param orden. Es la orden de fabricación a registrar.
 	 * @throws Exception. En caso de que se produzca un error, se lanza una excepción.
	 */
	public void registrar(OrdenFabricacionGeneral orden)
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		
		try{
			session.beginTransaction();
			session.saveOrUpdate(orden);
			session.getTransaction().commit();
		}
		
		catch(HibernateException he)
		{
			session.getTransaction().rollback();
			throw he;
		}
	}
	
	/**
	 * Método que registrar los renglones de una orden de fabricación en la base de datos
	 * @param renglones. Renglones de la orden de fabricación.
	 * @throws Exception. En caso de que se produzca un error, se lanza una excepción.
	 */
	public void registrarRenglones(Set<RenglonOrdenFabricacionGeneral> renglones)
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		
		try
		{
			session.beginTransaction();
			
			//guardamos cada uno de los renglones en la base de datos
			for(RenglonOrdenFabricacionGeneral renglon : renglones)
			{
				session.saveOrUpdate(renglon);
			}
			
			session.getTransaction().commit();
		}
		
		catch(HibernateException he)
		{
			session.getTransaction().rollback();
			throw he;
		}
	}
	
	
	/**
	 * Método que busca la orden de fabricación general cuyo número de orden sea igual al pasado como parámetro.
	 * @param nroOrden
	 * @return
	 */
	public OrdenFabricacionGeneral buscarOrdenFabricacionGeneral (Integer nroOrden) {
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		
		sess.beginTransaction();
		
		OrdenFabricacionGeneral ordenFabricacion = (OrdenFabricacionGeneral) sess.createQuery("FROM OrdenFabricacionGeneral O " +
															   	    "WHERE O.nroOrden = " + nroOrden).list().get(0);

		Hibernate.initialize(ordenFabricacion.getEmpleado());
		Hibernate.initialize(ordenFabricacion.getOrdenPedido());
		
		sess.close();
		
		return ordenFabricacion;
	}
	
	/**
	 * Método que busca en la base de datos las órdenes de fabricación que cumplan con los parámetros de filtrado.
	 * @param estado. Es el estado de la orden de fabricación.
	 * @param fechaEstimadaInicio. Es la fecha estimada de inicio de la orden de fabricación.
	 * @param fechaEstiamadaFinalizacion. Es la fecha estimada de finalización de la orden de fabricación.
	 * @param pReservasYCompras. Si el método se llamó de la pantalla reservas y compras.
	 * @return List<OrdenFabricacionGeneral>. Retorna una lista con las órdenes de fabricación.
	 */
	@SuppressWarnings("unchecked")
	public List<OrdenFabricacionGeneral> filtrar(String estado, String fechaEstimadaInicio, String fechaEstimadaFinalizacion, boolean pReservasYCompras)
	{
		List<OrdenFabricacionGeneral> ordenes;
		
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		
		session.beginTransaction();
		
		String hql = "FROM OrdenFabricacionGeneral " +
					 "WHERE estado LIKE '%" + estado + "'";
		
		if(pReservasYCompras)
			hql = hql + " AND estado NOT LIKE 'GUARDADA' AND estado NOT LIKE 'CERRADA'";
		
		if(fechaEstimadaInicio != "")
			hql = hql + " AND fechaPrevistaInicio >= '" + fechaEstimadaInicio + "'";
		
		if(fechaEstimadaFinalizacion != "")
			hql = hql + " AND fechaPrevistaFinalizacion <= '" + fechaEstimadaFinalizacion + "'";
		
		ordenes = session.createQuery(hql).list();
		
		//Para cada orden de fabricación general...
		for(OrdenFabricacionGeneral orden : ordenes)
		{
			Hibernate.initialize(orden.getOrdenPedido());
			Hibernate.initialize(orden.getOrdenPedido().getCliente());
			Hibernate.initialize(orden.getEmpleado());
			Hibernate.initialize(orden.getOrdenPedido().getRenglonOrdenPedidos());
			
			for(RenglonOrdenPedido renglon : orden.getOrdenPedido().getRenglonOrdenPedidos()) {
				
				if(renglon.getEquipoPatron() != null) {
					Hibernate.initialize(renglon.getEquipoPatron().getListaDeMateriales().getEstado());
				}
				else {
					Hibernate.initialize(renglon.getComponentePatron().getListaDeMateriales().getEstado());
				}
			}
			
			//Para cada renglon de la orden de fabricación general...
			for(RenglonOrdenFabricacionGeneral renglon : orden.getRenglonOrdenFabricacionGenerals()) {
				
				Hibernate.initialize(renglon.getFechaEstimadaFinalizacion());
				Hibernate.initialize(renglon.getFechaEstimadaInicio());
				Hibernate.initialize(renglon.getId().getIdRenglonOrdenFabricacion());
				
				//...si es un equipo, lo inicializo.
				if(renglon.getRenglonOrdenPedido().getEquipoPatron() != null) {
					Hibernate.initialize(renglon.getRenglonOrdenPedido().getEquipoPatron().getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron());
					Hibernate.initialize(renglon.getRenglonOrdenPedido().getEquipoPatron().getSubclaseEquipoPatron().getId().getCodigoSubclaseEquipoPatron());
					Hibernate.initialize(renglon.getRenglonOrdenPedido().getEquipoPatron().getSubclaseEquipoPatron().getClaseEquipoPatron().getNombre());
					Hibernate.initialize(renglon.getRenglonOrdenPedido().getEquipoPatron().getSubclaseEquipoPatron().getNombre());
					Hibernate.initialize(renglon.getRenglonOrdenPedido().getEquipoPatron().getListaDeMateriales().getEstado());
					Hibernate.initialize(renglon.getRenglonOrdenPedido().getEquipoPatron().getListaDeMateriales().getIdListaMateriales());
				}
				
				//...si es un componente, lo inicializo.
				else {
					Hibernate.initialize(renglon.getRenglonOrdenPedido().getComponentePatron().getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron());
					Hibernate.initialize(renglon.getRenglonOrdenPedido().getComponentePatron().getSubclaseEquipoPatron().getId().getCodigoSubclaseEquipoPatron());
					Hibernate.initialize(renglon.getRenglonOrdenPedido().getComponentePatron().getSubclaseEquipoPatron().getClaseEquipoPatron().getNombre());
					Hibernate.initialize(renglon.getRenglonOrdenPedido().getComponentePatron().getSubclaseEquipoPatron().getNombre());
					Hibernate.initialize(renglon.getRenglonOrdenPedido().getComponentePatron().getCodigoComponente());
					Hibernate.initialize(renglon.getRenglonOrdenPedido().getComponentePatron().getCodigoSubcomponente());
					Hibernate.initialize(renglon.getRenglonOrdenPedido().getComponentePatron().getListaDeMateriales().getEstado());
					Hibernate.initialize(renglon.getRenglonOrdenPedido().getComponentePatron().getListaDeMateriales().getIdListaMateriales());
				}
			}
		}
		
		session.close();
		
		return ordenes;
	}
	
	
	/**
	 * Método que busca en la base de datos todos los renglones de una orden de fabricación particular.
	 * @param nroOrdenFabricacion. Es el número de orden de fabricación para la cual se quieren buscar sus renglones.
	 * @return Set<RenglonOrdenFabricacionGenera>. Retorna una lista con los renglones de la orden de fabricacación.
	 */
	public Set<RenglonOrdenFabricacionGeneral> buscarRenglones(int nroOrdenFabricacion)
	{
		OrdenFabricacionGeneral orden;
		Set<RenglonOrdenFabricacionGeneral> renglones = new HashSet<RenglonOrdenFabricacionGeneral>();
		
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		
		session.beginTransaction();
		
		//buscamos la orden de fabricacion en la base de datos
		orden = (OrdenFabricacionGeneral) session.get(OrdenFabricacionGeneral.class, nroOrdenFabricacion);
		
		//si existe una orden de pedido con el número de orden pasado como parámetro...
		if(orden != null)
		{
			//inicializamos los datos de los renglones de la orden de fabricación general
			Hibernate.initialize(orden.getRenglonOrdenFabricacionGenerals());
			
			renglones = orden.getRenglonOrdenFabricacionGenerals();
			
			//para cada renglón de la orden de fabricación general, inicializamos el renglón de la orden de pedido relacionada
			for(RenglonOrdenFabricacionGeneral renglon : renglones)
			{
				Hibernate.initialize(renglon.getRenglonOrdenPedido());
				
				RenglonOrdenPedido renglonOrdenPedido = renglon.getRenglonOrdenPedido();
				
				//inicializamos el equipo patrón
				Hibernate.initialize(renglonOrdenPedido.getEquipoPatron());
				
				//si el renglón de la ornde de pedido tiene cargado un equipo, inicializamos sus datos
				if(renglonOrdenPedido.getEquipoPatron() != null)
				{
					Hibernate.initialize(renglonOrdenPedido.getEquipoPatron().getSubclaseEquipoPatron());
					Hibernate.initialize(renglonOrdenPedido.getEquipoPatron().getListaDeMateriales());
				}
				
				//caso contrario, inicializamos los datos del componente
				else
				{
					Hibernate.initialize(renglonOrdenPedido.getComponentePatron());
					Hibernate.initialize(renglonOrdenPedido.getComponentePatron().getSubclaseEquipoPatron());
					Hibernate.initialize(renglonOrdenPedido.getComponentePatron().getListaDeMateriales());
				}
			}
		}
		
		session.close();
		
		return renglones;
	}
	
	/**
	 * Método que busca la orden de fabricación general asociada a la orden de pedido cuyo número es pasado como parámetro
	 * @param nroOrdenPedido. Número de la orden de pedido asociada.
	 * @return OrdenFabricaciónGeneral. Devuelve la orden de fabricación general asociada a la orden de pedido.
	 */
	public OrdenFabricacionGeneral buscarPorOrdenPedido (long nroOrdenPedido) {
		
		OrdenFabricacionGeneral ordenFabricacion;
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		
		session.beginTransaction();
		
		String hql = "FROM OrdenFabricacionGeneral o " +
				     "WHERE o.ordenPedido.nroOrden = " + nroOrdenPedido;
		
		ordenFabricacion = (OrdenFabricacionGeneral) session.createQuery(hql).uniqueResult();
	
		session.close();
		
		return ordenFabricacion;
	}
}
